package org.kazuhiko.rpg.server.net;

import org.kazuhiko.rpg.server.model.Entity;
import org.kazuhiko.rpg.server.model.Position;
import org.kazuhiko.rpg.server.model.Rotation;
import org.kazuhiko.rpg.server.net.packet.PacketBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ActionSender
{
	private static final Logger logger = LoggerFactory.getLogger( ActionSender.class );
	
	private RPGSession session;
	
	/**
	 * Incoming packets
	 * ---------------------
	 * Outgoing packets
	 * 0 = send chat message
	 * 1 = teleport
	 * 2 = add entity
	 * 3 = move entity
	 */
	
	public ActionSender( RPGSession session )
	{
		this.session = session;
	}
	
	/**
	 * Sends a chat message to a player
	 * @param message
	 */
	public void sendChatMessage( String message )
	{
		sendChatMessage( -1, message );
	}
	
	/**
	 * Sends a chat message to a player
	 * @param id
	 * @param message
	 */
	public void sendChatMessage( int id, String message )
	{
		PacketBuilder bldr = new PacketBuilder( session.getPackets().getOutgoingPacket( 0 ) );
		bldr.putByte( "id", id );
		bldr.putString( "message", message );
		logger.trace( "Sending chat message: {}", message );
		session.send( bldr.toPacket() );
	}

	/**
	 * Moving a player to a position with rotation
	 * @param position
	 * @param rotation
	 */
	public void sendTeleport( Position position, Rotation rotation )
	{
		PacketBuilder bldr = new PacketBuilder( session.getPackets().getOutgoingPacket( 1 ) );
		bldr.putByte( "id", -1 );
		bldr.putShort( "x", (int)position.getX() );
		bldr.putShort( "y", (int)position.getY() );
		bldr.putShort( "z", (int)position.getZ() );
		bldr.putShort( "pitch", (int)rotation.getPitch() );
		bldr.putShort( "yaw", (int)rotation.getYaw() );
		bldr.putShort( "roll", (int)rotation.getRoll() );
		logger.trace( "Sending teleport" );
		session.send( bldr.toPacket() );
	}
	
	/**
	 * adding an entity to the local entities of the player
	 * @param entity
	 */
	public void sendAddEntity( Entity entity )
	{
		sendAddEntity( entity, entity.getId() );
	}
	
	/**
	 * adding an entity to the local entities of the player
	 * @param entity
	 * @param id
	 */
	public void sendAddEntity( Entity entity, int id )
	{
		PacketBuilder bldr = new PacketBuilder( session.getPackets().getOutgoingPacket( 2 ) );
		bldr.putByte( "id", id );
		bldr.putClassicString( "name", entity.getName() );
		bldr.putShort( "x", (int)entity.getPosition().getX() );
		bldr.putShort( "y", (int)entity.getPosition().getY() );
		bldr.putShort( "z", (int)entity.getPosition().getZ() );
		bldr.putShort( "pitch", (int)entity.getRotation().getPitch() );
		bldr.putShort( "yaw", (int)entity.getRotation().getYaw() );
		bldr.putShort( "roll", (int)entity.getRotation().getRoll() );
		logger.trace( "Sending add entity" );
		session.send( bldr.toPacket() );
	}
	
	/**
	 * Moves an entity
	 * @param entity
	 * @param deltaX
	 * @param deltaY
	 * @param deltaZ
	 * @param deltaP
	 * @param deltaYa
	 * @param deltaR
	 */
	public void sendMoveEntity( Entity entity, float deltaX, float deltaY, float deltaZ, float deltaP, float deltaYa, float deltaR )
	{
		PacketBuilder bldr = new PacketBuilder( session.getPackets().getOutgoingPacket( 3 ) );
		bldr.putByte( "id", entity.getId() );
		bldr.putShort( "delta_x", (int) deltaX );
		bldr.putShort( "delta_y", (int) deltaY );
		bldr.putShort( "delta_z", (int) deltaZ );
		bldr.putShort( "delta_pitch", (int) deltaP );
		bldr.putShort( "delta_yaw", (int) deltaYa );
		bldr.putShort( "delta_roll", (int) deltaR );
		logger.trace( "Sending move entity" );
		session.send( bldr.toPacket() );
	}
	
	/**
	 * Updates an entity
	 * @param entity
	 */
	public void sendUpdateEntity( Entity entity )
	{
		final Position position = entity.getPosition();
		final Position oldPosition = entity.getOldPosition();
		
		final Rotation rotation = entity.getRotation();
		final Rotation oldRotation = entity.getOldRotation();
		
		final float deltaX = -oldPosition.getX() - position.getX();
		final float deltaY = -oldPosition.getY() - position.getY();
		final float deltaZ = -oldPosition.getZ() - position.getZ();
		final float deltaP = -oldRotation.getPitch() - rotation.getPitch();
		final float deltaYa = -oldRotation.getYaw() - rotation.getYaw();
		final float deltaR = -oldRotation.getRoll() - rotation.getRoll();
		
		if( deltaX > Byte.MAX_VALUE || deltaX < Byte.MIN_VALUE ||
			deltaY > Byte.MAX_VALUE || deltaY < Byte.MIN_VALUE ||
			deltaZ > Byte.MAX_VALUE || deltaZ < Byte.MIN_VALUE ||
			deltaP > Byte.MAX_VALUE || deltaP < Byte.MIN_VALUE ||
			deltaYa > Byte.MAX_VALUE || deltaYa < Byte.MIN_VALUE ||
			deltaR > Byte.MAX_VALUE || deltaR < Byte.MIN_VALUE )
		{
			//Teleport
			sendTeleport( position, rotation );
		}
		else
		{
			//Move
			sendMoveEntity( entity, deltaX, deltaY, deltaZ, deltaP, deltaYa, deltaR );
		}
	}
	
	public void sendRemoveEntity( Entity entity )
	{
		//TODO: make this work
	}
}
